#!/usr/bin/env python3
"""Serve a local tacview file via sockets.
"""
import asyncio
from asyncio import CancelledError
import gzip
import zipfile
from pathlib import Path
from functools import partial

try:
    import uvloop  # type: ignore

    uvloop.install()
except (ModuleNotFoundError, NotImplementedError):
    pass


from tacview_client.config import get_logger

LOG = get_logger("tacview_client_server")


async def handle_req(
    reader: asyncio.StreamReader, writer: asyncio.StreamWriter, filename: Path
) -> None:
    """Send data."""
    try:
        LOG.info("Connection started...")
        if filename.suffix == ".gz":
            LOG.info("Opening gzfile...")
            fp_ = gzip.open(filename, "rb")
        elif zipfile.is_zipfile(filename):
            LOG.info("Opening zipfile...")
            zfile = zipfile.ZipFile(filename)
            fp_ = zfile.open(zfile.filelist[0], "r")
        else:
            fp_ = filename.open("rb")
        await reader.read(4026)

        while True:
            line = fp_.readline()
            if not line:
                LOG.info("No remaining line...sending term line and breaking...")
                break
            writer.write(line)
            await writer.drain()
        writer.write_eof()
        writer.close()
        await writer.wait_closed()
        LOG.debug("All lines sent...closing...")
    except (ConnectionResetError, BrokenPipeError, CancelledError):
        LOG.info("Cancel received..shutting down...")
        writer.close()

    except Exception as err:
        LOG.info(f"Unexepcted error! {err}")
        try:
            writer.close()
        except:
            pass
    LOG.info("Exiting...")


async def serve_file(filename: Path, port: int) -> None:
    server = await asyncio.start_server(
        partial(handle_req, filename=filename), "127.0.0.1", port
    )
    try:
        await server.serve_forever()
    except CancelledError:
        LOG.error("Cancel error caught! Shutting down file server...")
        server.close()


def main(filename: Path, port: int) -> None:
    """Read from Tacview socket."""
    LOG.info(f"Serving Tacview file {filename} 127.0.0.1:{port}. ..")
    loop = asyncio.get_event_loop()
    task = loop.create_task(serve_file(filename, port))
    try:
        loop.run_until_complete(task)
    except KeyboardInterrupt:
        LOG.info("Keyboard interupt!")
        task.cancel()
    except Exception as err:
        task.cancel()
        raise err


if __name__ == "__main__":
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument("--filename", type=Path, help="Filename for server")
    parser.add_argument("--port", type=int, help="Port for server")
    args = parser.parse_args()
    main(args.filename, args.port)
